<?php

namespace Bundle\FireIceBundle;

use Bundle\FireIceBundle\Cache;

use Symfony\Component\DependencyInjection\ContainerInterface;

use Bundle\FireIceBundle\Cache\FileCache;

use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;

class FireIceEngine implements \ArrayAccess
{
    /**
     * @var Symfony\Component\DependencyInjection\ContainerInterface
     */
    private $_container;

    public $modules;

    private $_dynamicRouter;

    private $_controllerBuilder;

    private $_currentNode;
    
    /**
     * Диспетчер событий
     * @var \Symfony\Component\EventDispatcher\EventDispatcher
     */
    private $_eventDispatcher;
    
    /**
     * 
     * @var FileCache
     */
    private $_filecache;

    public function __construct($container)
    {
        $this->_container = $container;

        $this->_dynamicRouter = new DynamicRouter($this);

        $this->_controllerBuilder = new ControllerBuilder($this);
        
        $this->_filecache = new Cache\FileCache($this);
        
        // создание объекта обработчика событий
        $this->_eventDispatcher = new EventDispatcher();
        
        // связывание общих событий с обработчиком событий
        $this->registerEventListeners();

        
    }

    private function registerEventListeners()
    {
    	// в дальнейшем названия событий надо вынести как константы для классов
    	$this->_eventDispatcher->connect('sitetree.page_created', array($this, 'onRoutingNeedsRebuild'));
    	$this->_eventDispatcher->connect('sitetree.page_modified', array($this, 'onRoutingNeedsRebuild'));
    	$this->_eventDispatcher->connect('sitetree.page_removed', array($this, 'onRoutingNeedsRebuild'));
    }
    
    public function setModuleManager(\Bundle\ModuleBundle\Interfaces\ModuleManagerInterface $mm)
    {
        $this->modules = $mm;
    }

    public function getModuleManager()
    {
        return $this->modules;
    }

    public function getDynamicRouter()
    {
        return $this->_dynamicRouter;
    }

    public function getControllerBuilder()
    {
        return $this->_controllerBuilder;
    }

    public function getControllersList($bundle = null)
    {
        die(\var_dump($this->_container));
        die(\var_dump($bundle));
    }

    public function getCurrentNode()
    {
        return $this->_currentNode;
    }

    public function setCurrentNode($node)
    {
        $this->_currentNode = $node;
    }
    
    /**
     * @return FileCache
     */
    public function getFileCache()
    {
    	return $this->_filecache;
    }
    
    public function getLogger()
    {
    	return $this->_container->get('logger');
    }

    public function offsetExists($id)
    {
        return $this->_container->has($id);
    }

    public function offsetGet($id)
    {
        return $this->_container->get($id);
    }

    public function offsetSet($id, $value)
    {
        throw new \LogicException('Service is read only');
    }

    public function offsetUnset($id)
    {
        throw new \LogicException('Service is read only');
    }

    public function getParameter($parameter)
    {
    	return $this->_container->getParameter($parameter);
    }
    
    public function hasParameter($parameter)
    {
    	return $this->_container->hasParameter($parameter);
    }
    
    public function getContainer()
    {
        return $this->_container;
    }
    
    /**
     * Информирование о наступлении события
     * @param $event
     */
    public function notify(Event $event)
    {
        $this->_eventDispatcher->notify($event);
    }
    
    /**
     * Обработка события, при котором необходима перестройка таблицы маршрутизации
     * @param Event $event
     */
    public function onRoutingNeedsRebuild(Event $event)
    {
    	$container = $this->_container;
        try
        {
            $repo = $container->get('doctrine.orm.default_entity_manager')->
                        getRepository('Bundle\TreeBundle\Entities\Tree');
            $targetModels = $repo->findAll();
            //$output->write(sprintf('Building routing for %d nodes.', count($targetModels)), true);
        }
        catch (\Exception $e)
        {
            //$output->write($e->getMessage(), true);
            throw $e;
        }

        foreach($targetModels as $model)
        {
            $nodeRouting = $container->get('fireice')->getDynamicRouter()->
                buildRoutingForNode($model);
        }
        
        // phpfile code
        $code = $container->get('fireice')->getControllerBuilder()->
                    getCode(false);
                    
        $fcache = $container->get('fireice')->getFileCache();

        $controller = $container->getParameter('fireice.route_generator.controller');
        $serialized = $container->getParameter('fireice.route_generator.collection_ser');
        
        //$output->write(sprintf('Target folder `%s`', $fcache->getTargetDirectory()), true);
        //$output->write(sprintf('Generated controller `%s%s%s`', $fcache->getTargetDirectory(), DIRECTORY_SEPARATOR , $controller), true);
        
        $fcache->store($controller, $code);

        //$output->write(sprintf('Writing generated routing collection to `%s%s%s`', $fcache->getTargetDirectory(), DIRECTORY_SEPARATOR ,$serialized), true);
        
        $fcache->store($serialized, serialize($container->get('fireice')->getDynamicRouter()->getRouteCollection()));

        //$output->write("Done.", true);
    	
    	// пытаемся удалить кэш роутинга
    	
            $routingFileCache = 
               array(
                   $this->_container->getParameter('kernel.cache_dir') . '/' . get_class($container['router']->getGenerator()) . '.php',
                   $this->_container->getParameter('kernel.cache_dir') . '/' . get_class($container['router']->getMatcher()) . '.php');
                   
        	foreach($routingFileCache as $file)
        	{
        	   if(!unlink($file))
        	   {
        	       throw new \Exception(sprintf('Can\'t remove file (%s) while rebuilding routing', $file));
        	   }
        	}
    }
}
